/**
 * Copyright &copy; 2012-2016 <a href="http://www.stars-soft.com/">EziCloud</a> All rights reserved.
 */
package com.xhsj.user.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 字符串工具类, 继承org.apache.commons.lang3.StringUtils类
 * @author suxl
 * @Date: 2018/8/21 13:51
 */
@Slf4j
public class StringUtils {
	public static final String SPACE = " ";
	public static final String EMPTY = "";
	public static final String LF = "\n";
	public static final String CR = "\r";
	public static final int INDEX_NOT_FOUND = -1;
	private static final int PAD_LIMIT = 8192;

    private static final char SEPARATOR = '_';
    private static final String CHARSET_NAME = "UTF-8";

    /**
     * 转换为字节数组
     * @param str
     * @return
     */
    public static byte[] getBytes(String str){
    	if (str != null){
    		try {
				return str.getBytes(CHARSET_NAME);
			} catch (UnsupportedEncodingException e) {
				return null;
			}
    	}else{
    		return null;
    	}
    }

    /**
     * @param
     * @return
     */
    public static String toString(Object val){
		if (Objects.isNull(val)) {
			return "";
		} else {
			return String.valueOf(val);
		}
    }


    public static <T> T toJavaBean(Object o,Class<T> clazz){
		JSONObject o1 = (JSONObject)JSON.toJSON(o);
		return (T) JSONObject.toJavaObject(o1, clazz);
	}

	/**
	 * 两个数之和
	 * @param value1
	 * @param value2
	 * @return
	 */
	public static String add(Object value1,Object value2){
		String val;
		if (isBlank(value1)){
			val=String.valueOf(value2);
		}else if(isBlank(value2)){
			val=String.valueOf(value1);
		}else{
			BigDecimal b1 = new BigDecimal(String.valueOf(value1));
			BigDecimal b2 = new BigDecimal(String.valueOf(value2));
			val= b1.add(b2).toString();
		}

		return val;
	}

	/**
	 * 两个数之差
	 * @param value1
	 * @param value2
	 * @return
	 */
	public static String sub(Object value1,Object value2){
		String val;
		if (isBlank(value1)){
			val=String.valueOf(value2);
		}else if(isBlank(value2)){
			val=String.valueOf(value1);
		}else{
			BigDecimal b1 = new BigDecimal(String.valueOf(value1));
			BigDecimal b2 = new BigDecimal(String.valueOf(value2));
			val=b1.subtract(b2).toString();
		}
		return val;
	}

	/**
	 * 两个数之积
	 * @param value1
	 * @param value2
	 * @return
	 */
	public static String mul(Object value1,Object value2,int scale){
		String val;
		if (isBlank(value1)){
			val=String.valueOf(value2);
		}else if(isBlank(value2)){
			val=String.valueOf(value1);
		}else{
			BigDecimal b1 = new BigDecimal(String.valueOf(value1));
			BigDecimal b2 = new BigDecimal(String.valueOf(value2));
			BigDecimal multiply = b1.multiply(b2);
			val = multiply.setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
		}
		return val;
	}

	/**
	 * 两个数之商
	 * @param value1
	 * @param value2
	 * @return
	 */
	public static String div(Object value1,Object value2,int scale){
		String val;
		if (isBlank(value1)){
			val=String.valueOf(value2);
		}else if(isBlank(value2)){
			val=String.valueOf(value1);
		}else{
			BigDecimal b1 = new BigDecimal(String.valueOf(value1));
			BigDecimal b2 = new BigDecimal(String.valueOf(value2));
			val=b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).toString();
		}
		return val;
	}



	public static boolean isBlank(Object o) {

		if (Objects.isNull(o)) {
			return true;
		}
		if (o instanceof String) {
			String cs = (String) o;
			int strLen;
			if (cs != null && (strLen = cs.length()) != 0) {
				for(int i = 0; i < strLen; ++i) {
					if (!Character.isWhitespace(cs.charAt(i))) {
						return false;
					}
				}
				return true;
			} else {
				return true;
			}
		}
		return false;
	}

    public static String upperCase(String str) {
        return str == null ? null : str.toUpperCase();
    }

	public static boolean isNotBlank(Object cs) {
		return !isBlank(cs);
	}

    /**
     * 是否包含字符串
     * @param str 验证字符串
     * @param strs 字符串组
     * @return 包含返回true
     */
    public static boolean inString(String str, String... strs){
    	if (str != null){
        	for (String s : strs){
        		if (str.equals(trim(s))){
        			return true;
        		}
        	}
    	}
    	return false;
    }

	public static String trim(String str) {
		return str == null ? null : str.trim();
	}

	/**
	 * 替换掉HTML标签方法
	 */
	public static String replaceHtml(String html) {
		if (isBlank(html)){
			return "";
		}
		String regEx = "<.+?>";
		Pattern p = Pattern.compile(regEx);
		Matcher m = p.matcher(html);
		String s = m.replaceAll("");
		return s;
	}

	/**
	 * 替换为手机识别的HTML，去掉样式及属性，保留回车。
	 * @param html
	 * @return
	 */
	public static String replaceMobileHtml(String html){
		if (html == null){
			return "";
		}
		return html.replaceAll("<([a-z]+?)\\s+?.*?>", "<$1>");
	}

	/**
	 * 转换为Double类型
	 */
	public static Double toDouble(Object val){
		if (val == null){
			return 0D;
		}
		try {
			return Double.valueOf(trim(val.toString()));
		} catch (Exception e) {
			return 0D;
		}
	}

	/**
	 * 转换为Float类型
	 */
	public static Float toFloat(Object val){
		return toDouble(val).floatValue();
	}

	/**
	 * 转换为Long类型
	 */
	public static Long toLong(Object val){
		return toDouble(val).longValue();
	}

	/**
	 * 转换为Integer类型
	 */
	public static Integer toInteger(Object val){
		return toLong(val).intValue();
	}

//	/**
//	 * 获得i18n字符串
//	 */
//	public static String getMessage(String code, Object[] args) {
//		LocaleResolver localLocaleResolver = (LocaleResolver) SpringContextHolder.getBean(LocaleResolver.class);
//		HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
//		Locale localLocale = localLocaleResolver.resolveLocale(request);
//		return SpringContextHolder.getApplicationContext().getMessage(code, args, localLocale);
//	}

	/**
	 * 获得用户远程地址
	 */
	public static String getRemoteAddr(HttpServletRequest request){
		String remoteAddr = request.getHeader("X-Real-IP");
        if (isNotBlank(remoteAddr)) {
        	remoteAddr = request.getHeader("X-Forwarded-For");
        }else if (isNotBlank(remoteAddr)) {
        	remoteAddr = request.getHeader("Proxy-Client-IP");
        }else if (isNotBlank(remoteAddr)) {
        	remoteAddr = request.getHeader("WL-Proxy-Client-IP");
        }
        return remoteAddr != null ? remoteAddr : request.getRemoteAddr();
	}

//	/**
//	 * 获取请求中token
//	 * @param request
//	 */
//	public static String obtainToken(HttpServletRequest request){
//		String token = null;
//		// 请求参数中包含access_token参数
//		if (request.getParameter(OAuth2AccessToken.ACCESS_TOKEN) != null) {
//			token = request.getParameter(OAuth2AccessToken.ACCESS_TOKEN);
//		}
//
//		// 头部的Authorization值以Bearer开头
//		String auth = request.getHeader("Authorization");
//		if (auth != null) {
//			token = auth.substring(6);
//		}
//		return token;
//	}

	/**
	 * 驼峰命名法工具
	 * @return
	 * 		toCamelCase("hello_world") == "helloWorld"
	 * 		toCapitalizeCamelCase("hello_world") == "HelloWorld"
	 * 		toUnderScoreCase("helloWorld") = "hello_world"
	 */
    public static String toCamelCase(String s) {
        if (s == null) {
            return null;
        }

        s = s.toLowerCase();

        StringBuilder sb = new StringBuilder(s.length());
        boolean upperCase = false;
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);

            if (c == SEPARATOR) {
                upperCase = true;
            } else if (upperCase) {
                sb.append(Character.toUpperCase(c));
                upperCase = false;
            } else {
                sb.append(c);
            }
        }

        return sb.toString();
    }

    /**
	 * 驼峰命名法工具
	 * @return
	 * 		toCamelCase("hello_world") == "helloWorld"
	 * 		toCapitalizeCamelCase("hello_world") == "HelloWorld"
	 * 		toUnderScoreCase("helloWorld") = "hello_world"
	 */
    public static String toCapitalizeCamelCase(String s) {
        if (s == null) {
            return null;
        }
        s = toCamelCase(s);
        return s.substring(0, 1).toUpperCase() + s.substring(1);
    }

    /**
	 * 驼峰命名法工具
	 * @return
	 * 		toCamelCase("hello_world") == "helloWorld"
	 * 		toCapitalizeCamelCase("hello_world") == "HelloWorld"
	 * 		toUnderScoreCase("helloWorld") = "hello_world"
	 */
    public static String toUnderScoreCase(String s) {
        if (s == null) {
            return null;
        }

        StringBuilder sb = new StringBuilder();
        boolean upperCase = false;
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);

            boolean nextUpperCase = true;

            if (i < (s.length() - 1)) {
                nextUpperCase = Character.isUpperCase(s.charAt(i + 1));
            }

            if ((i > 0) && Character.isUpperCase(c)) {
                if (!upperCase || !nextUpperCase) {
                    sb.append(SEPARATOR);
                }
                upperCase = true;
            } else {
                upperCase = false;
            }

            sb.append(Character.toLowerCase(c));
        }

        return sb.toString();
    }

	/**
	 * * 判断一个对象是否为空
	 *
	 * @param object Object
	 * @return true：为空 false：非空
	 */
	public static boolean isNull(Object object)
	{
		return object == null;
	}

	/**
	 * * 判断一个对象是否非空
	 *
	 * @param object Object
	 * @return true：非空 false：空
	 */
	public static boolean isNotNull(Object object)
	{
		return !isNull(object);
	}


	public static void main(String[] args) {
		String div = div(20, 100, 2);
		String mul = mul(400.00, div,2);
		System.err.println(div);
		System.err.println(mul);
	}

//	public static String[] split(String str, String separatorChars) {
//		return splitWorker(str, separatorChars, -1, false);
//	}

//	private static String[] splitWorker(String str, String separatorChars, int max, boolean preserveAllTokens) {
//		if (str == null) {
//			return null;
//		} else {
//			int len = str.length();
//			if (len == 0) {
//				return ArrayUtils.EMPTY_STRING_ARRAY;
//			} else {
//				List<String> list = new ArrayList();
//				int sizePlus1 = 1;
//				int i = 0;
//				int start = 0;
//				boolean match = false;
//				boolean lastMatch = false;
//				if (separatorChars != null) {
//					if (separatorChars.length() != 1) {
//						label87:
//						while(true) {
//							while(true) {
//								if (i >= len) {
//									break label87;
//								}
//
//								if (separatorChars.indexOf(str.charAt(i)) >= 0) {
//									if (match || preserveAllTokens) {
//										lastMatch = true;
//										if (sizePlus1++ == max) {
//											i = len;
//											lastMatch = false;
//										}
//
//										list.add(str.substring(start, i));
//										match = false;
//									}
//
//									++i;
//									start = i;
//								} else {
//									lastMatch = false;
//									match = true;
//									++i;
//								}
//							}
//						}
//					} else {
//						char sep = separatorChars.charAt(0);
//
//						label71:
//						while(true) {
//							while(true) {
//								if (i >= len) {
//									break label71;
//								}
//
//								if (str.charAt(i) == sep) {
//									if (match || preserveAllTokens) {
//										lastMatch = true;
//										if (sizePlus1++ == max) {
//											i = len;
//											lastMatch = false;
//										}
//
//										list.add(str.substring(start, i));
//										match = false;
//									}
//
//									++i;
//									start = i;
//								} else {
//									lastMatch = false;
//									match = true;
//									++i;
//								}
//							}
//						}
//					}
//				} else {
//					label103:
//					while(true) {
//						while(true) {
//							if (i >= len) {
//								break label103;
//							}
//
//							if (Character.isWhitespace(str.charAt(i))) {
//								if (match || preserveAllTokens) {
//									lastMatch = true;
//									if (sizePlus1++ == max) {
//										i = len;
//										lastMatch = false;
//									}
//
//									list.add(str.substring(start, i));
//									match = false;
//								}
//
//								++i;
//								start = i;
//							} else {
//								lastMatch = false;
//								match = true;
//								++i;
//							}
//						}
//					}
//				}
//
//				if (match || preserveAllTokens && lastMatch) {
//					list.add(str.substring(start, i));
//				}
//
//				return (String[])list.toArray(new String[list.size()]);
//			}
//		}
//	}

	public static String capitalize(String str) {
		int strLen;
		if (str != null && (strLen = str.length()) != 0) {
			int firstCodepoint = str.codePointAt(0);
			int newCodePoint = Character.toTitleCase(firstCodepoint);
			if (firstCodepoint == newCodePoint) {
				return str;
			} else {
				int[] newCodePoints = new int[strLen];
				int outOffset = 0;
				outOffset = outOffset + 1;
				newCodePoints[outOffset] = newCodePoint;

				int codepoint;
				for(int inOffset = Character.charCount(firstCodepoint); inOffset < strLen; inOffset += Character.charCount(codepoint)) {
					codepoint = str.codePointAt(inOffset);
					newCodePoints[outOffset++] = codepoint;
				}

				return new String(newCodePoints, 0, outOffset);
			}
		} else {
			return str;
		}
	}

	public static String uncapitalize(String str) {
		int strLen;
		if (str != null && (strLen = str.length()) != 0) {
			int firstCodepoint = str.codePointAt(0);
			int newCodePoint = Character.toLowerCase(firstCodepoint);
			if (firstCodepoint == newCodePoint) {
				return str;
			} else {
				int[] newCodePoints = new int[strLen];
				int outOffset = 0;
				outOffset = outOffset + 1;
				newCodePoints[outOffset] = newCodePoint;

				int codepoint;
				for(int inOffset = Character.charCount(firstCodepoint); inOffset < strLen; inOffset += Character.charCount(codepoint)) {
					codepoint = str.codePointAt(inOffset);
					newCodePoints[outOffset++] = codepoint;
				}

				return new String(newCodePoints, 0, outOffset);
			}
		} else {
			return str;
		}
	}

	/**
	 * 字符串补0
	 * @param str
	 * @param strLength
	 * @return
	 */
	public static String addZeroForNum(String str, int strLength) {
		int strLen = str.length();
		if (strLen < strLength) {
			while (strLen < strLength) {
				StringBuffer sb = new StringBuffer();
				sb.append("0").append(str);// 左补0
				// sb.append(str).append("0");//右补0
				str = sb.toString();
				strLen = str.length();
			}
		}
		return str;
	}

	/*map相关*/
	public static Double getDoubleValue(Map<String, Object> map, String key) {
		BigDecimal value = getMapValue(map, key, BigDecimal.class);
		return value == null ? 0d : value.doubleValue();
	}

	public static Float getFloatValue(Map<String, Object> map, String key) {
		BigDecimal value = getMapValue(map, key, BigDecimal.class);
		return value == null ? 0f : value.floatValue();
	}

	public static Date getDateValue(Map<String, Object> map, String key) {
		Object value = map.get(key);
		return value == null ? new Date() : new Date(value.toString());
	}

	public static Integer getIntegerValue(Map<String, Object> map, String key) {
		Object value = map.get(key);
		if(value != null)
		{
			try {
				return Integer.valueOf(value.toString());
			} catch (Exception e) {
				log.error("exception message:", e);
				return 0;
			}
		}
		return 0;
	}

	public static Long getLongValue(Map<String, Object> map, String key) {
		Object value = map.get(key);
		if(value != null)
		{
			try {
				return Long.valueOf(value.toString());
			} catch (Exception e) {
				log.error("exception message:", e);
				return null;
			}
		}
		return null;
	}

	public static String getStringValue(Map<String, Object> map, String key) {
		String value = getMapValue(map, key, String.class);
		return value == null ? "" : value;
	}

	public static <T> T getMapValue(Map<String, Object> map, String key, Class<T> clazz) {
		Object value = map.get(key);
		if (value == null) {
			return null;
		}
		return clazz.cast(value);
	}

	/**
	 * 获取利用反射获取类里面的值和名称
	 *
	 * @param obj
	 * @return
	 * @throws IllegalAccessException
	 */
	public static Map<String, Object> objectToMap(Object obj) throws IllegalAccessException {
		Map map = new HashMap();
		Class<?> clazz = obj.getClass();
		List<Field> fieldList = new ArrayList<>();
		while (clazz != null) {
			fieldList.addAll(Arrays.asList(clazz.getDeclaredFields()));
			clazz = clazz.getSuperclass();//找到所有父类的属性
		}
		for (Field field : fieldList) {
			field.setAccessible(true);
			Object value = field.get(obj);
			if (null != value) {
				map.put(field.getName(), value);
			}
		}
		return map;
	}

	/**
	 * 汉字转为拼音
	 * @param chinese
	 * @return
	 */
	public static String toPinyin(String chinese){
		String pinyinStr = "";
		char[] newChar = chinese.toCharArray();
		HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();
		defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);
		defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
		for (int i = 0; i < newChar.length; i++) {
			if (newChar[i] > 128) {
				try {
					pinyinStr += PinyinHelper.toHanyuPinyinStringArray(newChar[i], defaultFormat)[0];
				} catch (BadHanyuPinyinOutputFormatCombination e) {
					e.printStackTrace();
				}
			}else{
				pinyinStr += newChar[i];
			}
		}
		return pinyinStr;
	}

}
